package com.demo.cryptology.symmetric;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * DES 是一种对称加密算法，所谓对称加密：加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究，
 * 后来被美国政府正式采用，之后开始广泛流传，但是近些年使用越来越少，因为DES使用56位密钥，以现代计算能力，
 * 24小时内即可被破解。虽然如此，在某些简单应用中，我们还是可以使用DES加密算法，本文简单讲解DES的JAVA实现
 * 。
 * 注意：DES加密和解密过程中，密钥长度都必须是8的倍数
 */
public class DES {

    public static byte[] encrypt(byte[] datasource, String password) throws Exception {
        SecureRandom random = new SecureRandom();
        DESKeySpec desKey = new DESKeySpec(password.getBytes());
        //创建一个密钥工厂，然后用它把DESKeySpec转换成
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(desKey);
        //cipher对象世纪完成加密操作
        Cipher cipher = Cipher.getInstance("DES");
        //用密钥初始化cipher对象
        cipher.init(cipher.ENCRYPT_MODE, securekey, random);
        //现在，获取数据并加密
        //正式执行加密操作
        byte[] r = cipher.doFinal(datasource);
        return encoder.encode(r);
    }


    public static byte[] decrypt(byte[] src, String password) throws Exception {
        src = decoder.decode(src);
        //DES算法要求有一个可信任的随即数源
        SecureRandom random = new SecureRandom();
        DESKeySpec deskey = new DESKeySpec(password.getBytes("utf-8"));
        //创建一个密钥工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        //将DESKeySpec对象转换成secretKey对象
        SecretKey secretKey = keyFactory.generateSecret(deskey);
        //cipher对象世纪完成解密操作
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(cipher.DECRYPT_MODE, secretKey, random);
        return cipher.doFinal(src);

    }

    static final Base64.Decoder decoder = Base64.getDecoder();
    static final Base64.Encoder encoder = Base64.getEncoder();

    public static void main(String[] args) throws Exception {
        String str = "代价密数据";
        //长度是8的倍数
        String password = "1234567887654321";
        byte[] result = DES.encrypt(str.getBytes("utf-8"), password);
        System.out.println("加密后:" + new String(result, "utf-8"));

//        String baseStr = encoder.encodeToString(result);
//        System.out.println("base64加密des密文:" + baseStr);
//        byte[] resp = decoder.decode(baseStr.getBytes());
//        System.out.println("base解码des密文:" + new String(resp));

        byte[] decryResult = DES.decrypt(result, password);
        System.out.println("解密后:" + new String(decryResult));

    }

}
